וגם שיהיה יעיל.
יש כזה דבר? - איך?
23 תשובות
זה הלא יעיל והפשוט
וזה השליפה רנדומלית יעילה שמצריכה לקרוא מדריך של 100 שורות לפני
קראתי את המדריך ויש בעייה עם השימוש בלימיט במצב כזה, בגלל:
שאם לגולש יצא את המספר 20(נניח),אז יוצג לו בדף את שורה מספר 21(כי זה דילג על 20 שורות).
עכשיו מה יקרה אם מחקתי את שורה מס' 10. אז הגולש לדף 20 יוצג בכלל את השורה 22 -ולא 21 כמו קודם.
וזה יכול לבאס גולש שהגיע מגוגל או מקישור כל שהוא(מועדפים וכו')
מה הפתרון?
אתה לא מגריל את ה id של השורה שצריך להציג,
אתה מגריל את המספר הסידורי (הסדר) של השורה בטבלה.
תמיד יש שורה שמספרה 20 בטבלה, גם אם ה id שלה הוא 5811
נכון, ואתה מסכים שהיום שורה מס' 20 בטבלה זה פוסט בנושא X, ומחר אם אני ימחוק שורה אז המיקום של 20 שורות יהיה שונה ולכן הפוסט יהיה Y. נכון?
ואני רוצה לתת לגולש אפשרות של לשמור קישור כך שאצטרך להגדיר GET מסויים וע"פ זה לשלוף או משהנו כזה..
יש פתרון?
במקרה כזה השליפה היא בכלל לא רנדומלית :)
אתה יכול לשמור בטבלה נפרדת קישור בין קוקי של משתמש שתיתן למשתמש
לבין הפוסט שהיגרלת בכניסה הראשונה שלו לאתר.
אם אתה רוצה שהוא יוכל לתת את זה בתור קישור לחבר - באמת תצטרך לעשות את זה על בסיס קישור עם איזה פרמטר בכתובת, אבל המימוש ישאר זהה.
אם בן אדם נכנס בלי פרמטר בכתובת - אתה שם בטבלה מספר כלשהו x ואת האידי של השורה שהוגרלה
ומפנה את הדפדפן לכתובת עם הפרמטר x.
אני חשבתי ואז הגעתי לפתרון, וזה כן רנדומלי:
הסבר: אני משלב בין לימיט לבין שליפה ע"פ ID.
פירוט: אני שולף מהמסד שורה רנדומלית ע"י מספר שהגרלתי(מ-0 עד למספר השורות שבמסד-1)
לדוגמא יש לי טבלה עם 50 שורות, והוגרל המספר 25. אז השורה מס' 26 תשלף.
אבל לגולש אני לא יציג ע"פ הלימיט אלא ע"פ הID של אותה שורה.
זאת אומרת שהמזהה היחודי של השורה שנבחרה מהלימיט, תכנס לGET ושם אני ישלוף את המספר ויציג לו את השורה הזהה לID מה"גט".
ובכך הרווחתי שתמיד יוצג לו שורה שקיימת במסד. ושיש לו קישור לאותו הפוסט.
כי אם נשתמש רק בלימיט אז עכשיו נשלף לו שורה מס' 26, ומה יקרה אם מחקתי את שורה מס' 10 - אז שהוא יכנס לקישור ששמר, בעצם יוצג לו השורה מס' 27 ולא 26. כי הלימיט סופר שורות ביחס לטבלה.
ואם נשתמש בID אז יכול להיות שיוגרל ID מחוק.
לעומת זאת אם נשתמש בשניהם כמתואר לעיל - הכל מצויין!
אשמח לשמוע הערות(לחיוב ולשלילה)
נ.ב איך עדיף להגריל מס' רנדומלי: ע"י סקריפט PHP או ע"י שאילתה(ואז יהיה לי 3 שאילתות, לעומת זאת אם אשתמש בסקריפט PHP אז יהי 2 שאילתות - ספירת שורות ושליפה של השורה)
פתרון מעולה :)
בקשר לשאילתות: תהיה לך רק שאילת אחת אם היא גם תגריל מספר וגם תחזיר שורה שאת ה id שלה תיקח.
לא כל כך הבנתי את הפונקצייה FLOOR - מה היא עושה?
אני אסביר לך בהודעה הבאה, אבל באמת מעניין אותי אם יש לך ניחושים מה יכולה לעשות פונקציה "ריצפה" שמקבלת שבר עשרוני.
כן, קראתי שהיא מעגלת מספר כלפי מטה. נוו..
נ.ב. עכשיו קראתי גם על הפונקצייה RAND() בMYSQL. ולפי מה שהבנתי, היא מחזירה מספר אקראי בין 0' ל 1' שזה נראה כך בדרך כלל: 0.45445654645 ולכן אם נריץ בלולאה 3 פעמים אז נקבל:
1 - 0.523423432432
2- 0.2324324234324
3 - 0.346546546456456
ואז כשאשתמש עם ORDER BY RAND() אז הוא יסדר ע"פ גודל המספר ולכן השורות שלעיל יסתדרו כך:
1 - ...
3 - ....
2 - ......
הייתי חייב לציין זאת כי זה הפעם הראשונה שבאמת הבנתי איך זה עובד
ואם כך: הפונקצייה FLOOR היא תעגל את המספר שייצר הRAND() כך שתמיד התוצאה הסופית תהיה 0' - כי היא מורידה את כל מה שארי הנקודה(העשרוני).
ואז בשאילתה שהבאת בהודעה שלך לעיל. יוצא שהיא מבצעת: 0 כפול מספר השורות בטבלה(נניח 50)
אז איך יש פה תוצאה רנדומלית בדיוק???
או בקיצור, לא הבנתי את השאילתה הזאת:
SELECT FLOOR( RAND() * COUNT(*))
אפשר להסביר?
RAND מחזירה מספר בין 0 ל-1.
אנחנו מכפילים את זה במספר השורות בטבלה (COUNT). כולמר, אנחנו מקבלים מספר בין 0 לבין מספר השורות בטבלה.
אחר כך, כדי להוריד את מה שאחרי הנקודה העשרונית, משתמש ב-FLOOR.
כן, הבעייה שלי הייתה בחשבון, שחשבתי שהכפלה בשבר עשרוני זה כמו הכפלה ב-0' (שלפני הנקודה)
ועכשיו בדקתי ומתברר שהתרגיל הזה לדוגמא: 0.435435 * 50 שווה 21.77175 ואז יש את FLOOR שמוריד את הנקודה ומה שאחריה כך שנשאר 21.
הבנתי :)
עוד דבר אחד:
מה יותר יעיל? - הגרלת מספר ע"י שאילתה כמתואר לעיל, או הגרלה ע"י PHP - MT_RAND??
אם אני יגריל עם שאילתה אז יהיה 2 שאילתות[1.ספירת שורות 2.הגרלת מספר ושליפתו] ועוד שאילתה שמציגה את הפוסט
ואם אשתמש בPHP להגרלת המספר אז יהיה רק שאילתה אחת[1.ספירת השורות] והPHP יגריל מספר שיכנס לשאילתה של הצגת הפוסט.
מה עדיף?
[לפי מה שאני יודע: השאילתה תתבצע יותר מהר מהסקריפט אבל מצד שני יהיה יותר שאילתות שרצות]
מה עדיף?
ככה או ככה יהיו לך שני שאילתות. אחת לקבל את כמות השורות והשניה לבחור שורה מסוימת.
למזלך אפשר לעשות את שניהם בשאילת אחת, שזה חוסך לך בזמן ותעבורה בין הסקריפט לבין המסד נתונים.
חשבתי על השאילתה הבאה, האם היא אפשרית?:
שבעצם אני שולף את הID של השורה, איפה שהלימיט מדלג על X שורות.
וכך יוצא שבשאילתה אחת שלפתי גם את כמות השורות, גם הגרלתי מס' מספר, וגם קיבלתי את הID של השורה
ואז נשאר לעשות רק את השאילתה שתציג את הפוסט.
מה אתה אומר, זה אפשרי שאילתה שכזאת?
תנסה ותגלה לבד. :)
נו באמת אין לי כוח אתה יודע או שאני יהיה מוכרח לנסות....?
ואוווווווווו איזה טמבל, עכשיו אחזתי שמה שבעצם אמרתי זה היה כתוב גם בכתבה שלך אלכס.
ואתה עוד אומר לי "פתרון מעולה :)"
רק שבעצם אתה עשית 2 שאילתות:
1) קבלת מס' אקראי - ע"י מספר השורות שבמסד כפול מספר אקראי בין 0 ל1 ועיגול המספר(שלא יהיה עשרוני)
2)שליפה של שורה בטבלה ע"פ הלימיט שידלג על מס' שורות רנדומלי - מהשאילתה הקודמת.
ובגלל שאני רוצה שיהיה גם קישור לדף האקראי אז אני לא שולף את הפוסט ע"פ הלימיט. אלא אני רק שולף את השורה בשבילי ע"י הלימיט ואז אני מכניס את הID של השורה לתוך GET וע"פ זה אני שולף למשתמש
אבל בעצם הקוד שבכתבה הוא אותו דבר כמו מה שאני צריך, אז למה לעזאזאל אמרת לי פתרון מעולה..?
ולעידן: כתוב שם שאי אפשר את השאילתה ששאלתי אבל אני ינסה אני לא מאמין
כי כרנאה הפתרון היה בדיוק מה שהיית צריך :)
אני שמח שהגעת אליו לבד. זה הרבה יותר מעשיר מסתם לקרוא את התשובה שלי :)
אוקקי אז בעצם עכשיו יש לי 3 שאילתות, 2 כמו שבכתבה שלך(1.סופר את השורות ומגריל מספר 2.שולף שורה ע"פ המספר הרנדומלי בלימיט -יחסית לטבלה ולא ע"פ id)
ועכשיו הוספתי שאילתה שלישית שישלוף פוסט ע"פ הID של השורה - שהתקבל לי מהשאילתה השנייה -כי אני רוצה שיהיה קישור קבוע לזה..
יש איזה דרך לצמצם בשאילתה? שיהיה אולי פחות שאילתות ?
צריך לציין ששני השאילתות הראשונות קוראות בבקשה הראשונה לשרת,
השאילתה השלישית קוראת בבקשה השניה לשרת, אחרי רידיירקט.
את שני השאילתות אפשר לצמצם לאחת
את השלישית אפשר בחלק מהמקרים לחסוך אם בבקשה הראשונה תכניס את הנתונים של אותה שורה לסשן. אחרי ההפנייה, למרות שבקישור יהיה ID , תוכל לקחת את הערך מהסשן.
אבל אין באמת צורך לעשות את זה. 3 שאילתות זה ממש לא הרבה.
בטח רק בשביל להציג את העמוד שאתה מתסכל עליו כרגע התבצעו לפחות עשר.
לא הבנתי איך אפשר לצמצם את 2 השאילתות הללו לשאילתה אחת?
הנה 2 השאילתות:
הרי אמרת שם בכתבה במפורש שאי אפשר לתת תת שליפה כפרמטר בלימיט(בדקתי את זה ואתה צודק)